package org.example.judge.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.example.judge.oj.GoJudge;
import org.example.judge.oj.GoJudgeDruid;
import org.example.judge.oj.JudgeResult;
import org.example.judge.service.ProblemService;
import org.example.judge.service.SubmitService;
import org.example.judge_common.annotation.AuthAnnotation;
import org.example.judge_common.entity.PageResult;
import org.example.judge_common.entity.RequestSubmitParams;
import org.example.judge_common.entity.ResponseResult;
import org.example.judge_common.hander.RetrunMsgException;
import org.example.judge_common.rank.AllUserRank;
import org.example.judge_common.util.CompileUnit;
import org.example.judge_common.util.MyUtils;
import org.example.judge_feign_api.ContestClient;
import org.example.judge_pojo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
@CrossOrigin //解决跨域问题
@RequestMapping("/submit")
public class SubmitController {
    @Autowired
    private RedisTemplate redisTemplate;

    @Qualifier("SubmitServiceImpl")
    @Autowired
    private SubmitService submitService;

    @Autowired
    private GoJudgeDruid goJudgeDruid;

    @Qualifier("ProblemServiceImpl")
    @Autowired
    private ProblemService problemService;

    @Autowired
    private ContestClient contestClient;

    /**
     * 用户做题记录分析
     * @param request
     * @return
     */
    @PostMapping("/progress")
    @ResponseBody
    @AuthAnnotation({Auth.CLIENT})
    public ResponseResult progress(HttpServletRequest request,String errorStatus,String userId){
//        if(params==null)params = new RequestProblemParams();
        User loginUser = (User) request.getAttribute("loginUser");
        if(MyUtils.isNotEmpty(userId)){
            loginUser.setId(userId);
        }
//        if(!Auth.isAdmin(loginUser))params.setAuth(0); //不能查看私密题目
//        if(loginUser!=null)params.setUserId(loginUser.getId());
        HashMap<String, Integer> res = new HashMap<>(4);
        if(MyUtils.isEmpty(errorStatus)){
            // 提交通过的数量
            Integer acceptSubmitCount = submitService.getSumbitSum(null, loginUser.getId(), 0);
            // 提交的数量
            Integer submitCount = submitService.getSumbitSum(null, loginUser.getId(), null);
            // 解题成功的题目数量
            Integer acceptProblemCount = submitService.getSuccessProblemSum(loginUser.getId(), true);
            // 一共尝试解题的总数
            Integer submitProblemCount = submitService.getSuccessProblemSum(loginUser.getId(), false);

            res.put("acceptSubmitCount",acceptSubmitCount);
            res.put("submitCount",submitCount);
            res.put("acceptProblemCount",acceptProblemCount);
            res.put("submitProblemCount",submitProblemCount);
        }else{
            // 提交指定结果的数量
            Integer acceptSubmitCount = submitService.getSumbitSum(null, loginUser.getId(), Integer.parseInt(errorStatus));
            res.put("count",acceptSubmitCount);
        }

        return ResponseResult.success().setData(res);
    }

    @PostMapping("/search")
    @AuthAnnotation({Auth.CLIENT})
    public ResponseResult search(RequestSubmitParams params,HttpServletRequest request){
        User loginUser = (User) request.getAttribute("loginUser");  //查看自己
        if("me".equalsIgnoreCase(params.getUserId()))params.setUserId(loginUser.getId());
        PageResult<Submit> res = submitService.search(params);

        for (Submit submit : res.getDataList()) {
            if(MyUtils.isNotEmpty(submit.getContestId())&&!submit.getUserId().equals(loginUser.getId())&&!Auth.isAdmin(loginUser)){
//                Object status = contestClient.getContestById(submit.getContestId(), "status").getData();
                Object o = redisTemplate.opsForValue().get(submit.getContestId()); //使用缓存

                if(o!=null&&JSON.parseObject(o.toString(), Contest.class).getStatus()==1){
                    submit.setCode("代码将在比赛结束后公开");
                }
            }
            Problem problem = problemService.getById(submit.getProblemId());
            if(problem.getAuth()==2&&!submit.getUserId().equals(loginUser.getId())&&!Auth.isAdmin(loginUser)){  //比赛中的
                submit.setCode("代码将在比赛结束后公开");
            }

        }
        return ResponseResult.success().setData(res);
    }

    /**
     * 用户提交判题
     *
     * @param submit
     * @param request
     * @return
     */
    @PostMapping(value = "/main")
    @AuthAnnotation({Auth.CLIENT})
    public ResponseResult submit(@RequestBody Submit submit, HttpServletRequest request) {
        if(MyUtils.isEmpty(submit.getCode())||MyUtils.isEmpty(submit.getLanguage())){
            return ResponseResult.fail("代码或编译器不能为空");
        }
        User loginUser = (User) request.getAttribute("loginUser"); //登录用户
        String ip = request.getLocalAddr();  //ip地址

        if(MyUtils.isEmpty(submit.getIp()))submit.setIp(ip);
        if(MyUtils.isEmpty(submit.getUserId()))submit.setUserId(loginUser.getId());

        submitService.save(submit);
        return ResponseResult.success().setData(submit.getId());
    }
    /**
     * 重新判题
     *
     * @param id
     * @param request
     * @return
     */
    @PostMapping(value = "/reload/{id}")
    @AuthAnnotation({Auth.ADMINISTRATOR})
    public ResponseResult submitReload(@PathVariable("id") String id, HttpServletRequest request) {

        Submit byId = submitService.getById(id);
        if(byId==null)return ResponseResult.fail("不存在的提交记录");
        //将提交信息保存到redis,保存2分钟
        redisTemplate.opsForValue().set(byId.getId(), JSON.toJSONString(byId), 2, TimeUnit.MINUTES);

        //发送id到提交队列
        redisTemplate.opsForList().leftPush("submit", byId.getId());
        return ResponseResult.success();
    }

    @PostMapping(value = "/result/{id}")
    @AuthAnnotation({Auth.CLIENT})
    public ResponseResult submitById(@PathVariable String id,HttpServletRequest request){
        Submit byId = submitService.getById(id);

        if(byId==null)return ResponseResult.fail("查无结果");

        //数据处理
//        if(byId.getShare()==1){//代码不可见
//            User loginUser = (User) request.getAttribute("loginUser");
//            if (!loginUser.getId().equals(byId.getUserId())) {
//                byId.setCode(null);
//            }
//        }
        return ResponseResult.success().setData(byId);
    }

    /**
     * 返回用户的上一次提交
     * @param problemId problemId
     * @param request
     * @return
     */

    @PostMapping(value = "/last/{id}")
    @AuthAnnotation({Auth.CLIENT})
    public ResponseResult submitLastById(@PathVariable("id") String problemId,String userId,HttpServletRequest request){
        User loginUser = (User) request.getAttribute("loginUser"); //登录用户
        if(MyUtils.isNotEmpty(userId)){
            loginUser.setId(userId);
        }
        Submit byId = submitService.lastSubmit(problemId,loginUser.getId());

//        if(byId==null)return ResponseResult.fail("查无结果");

        //数据处理

        return ResponseResult.success().setData(byId);
    }

    /**
     * 自定义测试样例
     *
     * @param submit .code 代码

     * @return
     */
    @PostMapping(value = "/test")
    @AuthAnnotation({Auth.CLIENT})
    public ResponseResult submitTest(@RequestBody Submit submit) throws RetrunMsgException {

        if (MyUtils.isEmpty(submit.getLanguage())) {
            return ResponseResult.fail("未选择编译器语言类型");
        }

        GoJudge goJudge = goJudgeDruid.getTestGoJudge();
        if (goJudge == null) return ResponseResult.fail("评测机繁忙，请稍后重试");
        try {
            JudgeResult res = goJudge.run(submit.getTestInput(), submit.getTestOutput(), submit.getCode(), 1000l, 512 * 1024l, CompileUnit.get(submit.getLanguage()));
            return ResponseResult.success().setData(res);
        }catch (Exception e){
            e.printStackTrace();
            return  ResponseResult.fail("评测机繁忙，请稍后重试");
        }finally {
            goJudge.close();
        }
//        return  ResponseResult.fail("评测机繁忙，请稍后重试");
    }

    /**
     * 查询做题通过数用户名单
     */
    @PostMapping("/accept/rank")
    public ResponseResult acceptRank(Integer page,Integer size,String beginTime){

        PageResult<AllUserRank> allUserRankSubmit = submitService.getAllUserRankSubmit(page, size,beginTime);
        return ResponseResult.success().setData(allUserRankSubmit);
    }


}
